/*
 * @Descripttion : Picker 构造函数 (子集：year, month, date, time)
 * @Author       : QianFox Team
 * @Date         : 2022-03-03 15:01:12
 * @LastEditors  : Please set LastEditors
 * @LastEditTime : 2023-02-28 16:49:45
 */

import { Popper } from './popper';
import { _nowDatetime, _typeOf } from './common/utils';

function Picker() {
    Popper.call(this);
    this.MENU = '.foxui-picker-menu';
    this.CLEAR_HANDLE = '.foxui-picker-handle:not(.is-disabled)';
    this.CLEAR = '.foxui-picker-handle .foxui-icon-cuowu-o'; // 当前组件清空 icon
    this.CONTAINER = '.foxui-picker';
    this.PREV_TEN_YEAR_BTN = '.foxui-picker-body__year .prev-year-btn';
    this.NEXT_TEN_YEAR_BTN = '.foxui-picker-body__year .next-year-btn';
    this.PREV_YEAR_BTN_YEAR = '.foxui-picker-body__month .prev-year-btn';
    this.NEXT_YEAR_BTN_YEAR = '.foxui-picker-body__month .next-year-btn';
    this.PREV_YEAR_BTN_DATE = '.foxui-picker-body__date .prev-year-btn';
    this.NEXT_YEAR_BTN_DATE = '.foxui-picker-body__date .next-year-btn';
    this.PREV_DATE_BTN = '.foxui-picker-body__date .prev-month-btn';
    this.NEXT_DATE_BTN = '.foxui-picker-body__date .next-month-btn';
    this.BODY = '.foxui-picker-body';
    this.BODY_YEAR = '.foxui-picker-body__year';
    this.BODY_MONTH = '.foxui-picker-body__month';
    this.BODY_DATE = '.foxui-picker-body__date';
    this.INPUT = '.foxui-picker-handle input';
}

Object.setPrototypeOf(Picker.prototype, Popper.prototype);

Picker.prototype._init = function () {
    this._bindClearInput();
    this._bindMenuStopPropagation();
    this._bindAdjustTenYear();
    this._bindAdjustYear();
    this._bindAdjustDate();
};

Picker.prototype._bindMenuStopPropagation = function () {
    $(document).on('click', this.MENU, function (event) {
        // 阻止点击 menu 面板冒泡
        event.stopPropagation();
    });
};

Picker.prototype._bindToggle = function (callback) {
    let that = this;
    $(document).on('click', this.HANDLE, function (event) {
        event.stopPropagation();

        let $handle = $(this),
            $menu = $handle.siblings(that.MENU),
            isActive = $handle.is('.is-active'),
            len = $menu.length;

        // 弹出框显示/隐藏
        if (isActive) {
            $handle.removeClass('is-active');
            $menu.slideUp('fast');
            // input 失去焦点
            $handle.find('input').blur();
        } else {
            // 追加节点/替换节点
            if (len > 0) {
                $menu.empty().append(
                    that._panelHtml({
                        topHtml: that._topHtml(this),
                        bodyHtml: that._bodyHtml(this),
                        bottomHtml: that._bottomHtml(),
                    })
                );
            } else {
                $handle.closest(that.CONTAINER).append(
                    `<div class="foxui-picker-menu">${that._panelHtml({
                        topHtml: that._topHtml(this),
                        bodyHtml: that._bodyHtml(this),
                        bottomHtml: that._bottomHtml(),
                    })}</div>`
                );
            }
            // 关闭所有的 menus
            that._clearMenus();
            // 设置弹出面板的位置(需放在显示前，否则会跳动);
            that._setPosition(this);
            // 显示
            $handle.addClass('is-active');
            $handle.siblings(that.MENU).slideDown('fast'); // 不能用之前的 $menu，追加之前的，这个对象不存在
            // input 获取焦点
            $handle.find('input').focus();

            // 如传入回调函数据，则执行回调函数
            if (_typeOf(callback) === 'function') {
                callback(this);
            }
        }
    });
};

/**
 * @description: 生成 foxui-picker-panel html
 * @param {*} topHtml
 * @param {*} bodyHtml
 * @param {*} bottomHtml
 * @return {*}
 * @Date: 2022-03-04 10:44:22
 */
Picker.prototype._panelHtml = function ({ topHtml, bodyHtml, bottomHtml }) {
    let htmlArr = [
        '<div class="foxui-picker-panel">',
        `<div class="foxui-picker-top" style="display: ${topHtml ? 'block' : 'none'}">`,
        `${topHtml || ''}`,
        '</div>',
        '<div class="foxui-picker-body">',
        `${bodyHtml}`,
        `</div>`,
        `<div class="foxui-picker-bottom" style="display: ${bottomHtml ? 'block' : 'none'}">`,
        `${bottomHtml || ''}`,
        '</div>',
        '</div>',
    ];
    return htmlArr.join('');
};

/**
 * @description: 生成 content html
 * @param {*} htmlArr      td html 数组
 * @param {*} num          每个tr里放多少个td（year:4; month:4; date:7）
 * @param {*} type         类型（year month date）
 * @param {*} isHidden     是否显示 (ture, false)
 * @return {*}
 * @Date: 2022-03-03 22:14:46
 */
Picker.prototype._contentHtml = function ({ htmlArr, num, type, isHidden }) {
    let html = '';
    for (var i = 0, len = htmlArr.length; i < len; i += num) {
        html += `<tr>${htmlArr.slice(i, i + num).join('')}</tr>`;
    }
    return `<div class="foxui-picker-content"><table cellspacing="0" cellpadding="0" class="foxui-${type}-table" style="${!isHidden ? '' : 'display: none'}"><tbody>${html}</tbody></table></div>`;
};

/**
 * @description: 生成 header html
 * @param {*} year
 * @param {*} month
 * @param {*} type
 * @return {*}
 * @Date: 2022-03-04 14:26:09
 */
Picker.prototype._headerHtml = function ({ year, month }, type) {
    let htmlArr = [];
    let showYear = '',
        showMonth = '',
        dateYear = '',
        dateMonth = '';
    if (type === 'date') {
        showYear = `${year} 年`;
        dateYear = year;
        showMonth = `${month} 月`;
        dateMonth = month;
        htmlArr = [
            `<button class="foxui-text prev-year-btn"><i class="foxui-icon-shuangxiangzuo-o"></i></button>`,
            `<button class="foxui-text prev-month-btn"><i class="foxui-icon-xiangzuo-o"></i></button>`,
            `<span class="year" data-value="${dateYear}">${showYear}</span>`,
            `<span class="month" data-value="${dateMonth}">${showMonth}</span>`,
            `<button class="foxui-text next-year-btn"><i class="foxui-icon-shuangxiangyou-o"></i></button>`,
            `<button class="foxui-text next-month-btn"><i class="foxui-icon-xiangyou-o"></i></button>`,
        ];
    } else if (type === 'month') {
        showYear = `${year} 年`;
        dateYear = year;
        htmlArr = [
            `<button class="foxui-text prev-year-btn"><i class="foxui-icon-shuangxiangzuo-o"></i></button>`,
            `<span class="year" data-value="${dateYear}">${showYear}</span>`,
            `<button class="foxui-text next-year-btn"><i class="foxui-icon-shuangxiangyou-o"></i></button>`,
        ];
    } else if (type === 'year') {
        const startYear = year - parseInt(year % 10);
        const endYear = startYear + 9;
        dateYear = year;
        showYear = `${startYear} 年 - ${endYear} 年`;
        htmlArr = [
            `<button class="foxui-text prev-year-btn"><i class="foxui-icon-shuangxiangzuo-o"></i></button>`,
            `<span class="year" data-value="${dateYear}">${showYear}</span>`,
            `<button class="foxui-text next-year-btn"><i class="foxui-icon-shuangxiangyou-o"></i></button>`,
        ];
    }
    return `<div class="foxui-picker-header">${htmlArr.join('')}</div>`;
};

/**
 * @description: 生成 年份 html
 * @param {*} inputValue       输入框 年份
 * @param {*} year             年份
 * @param {*} isHidden         是否隐藏
 * @return {*}
 * @Date: 2022-03-04 14:18:57
 */
Picker.prototype._bodyYearHtml = function ({ inputValue, year }, isHidden) {
    let nowYear = _nowDatetime().year;
    year = parseInt(year) || nowYear;
    inputValue = parseInt(inputValue) || '';

    // 当前 10 年 html (content)
    let htmlArr = [];
    let startYear = year - parseInt(year % 10);
    for (let i = 0; i < 10; i++) {
        let classArr = ['available'];
        parseInt(startYear + i) === nowYear && classArr.push('today');
        parseInt(startYear + i) === inputValue && classArr.push('current');
        htmlArr.push(`<td class="${classArr.join(' ')}" data-value="${startYear + i}"><span class="cell">${startYear + i}</span></td>`);
    }

    // foxui-picker-header html
    let headerHtml = this._headerHtml({ year }, 'year');

    // foxui-picker-content hmtl
    let contentHtml = this._contentHtml({
        htmlArr,
        num: 4,
        type: 'year',
        isHidden: false,
    });

    return `<div class="foxui-picker-body__year" style="${!isHidden ? '' : 'display: none'}">${headerHtml + contentHtml}</div>`;
};

/**
 * @description: 绑定前/后十年
 * @param {*}
 * @return {*}
 * @Date: 2022-03-04 15:08:35
 */
Picker.prototype._bindAdjustTenYear = function () {
    let that = this;
    $(document).on('click', this.PREV_TEN_YEAR_BTN, function () {
        that._adjustTenYear(this, 'prev');
    });

    $(document).on('click', this.NEXT_TEN_YEAR_BTN, function () {
        that._adjustTenYear(this, 'next');
    });
};

/**
 * @description: 前/后十年
 * @param {*} button     点击按钮
 * @param {*} type       类型：next, prev
 * @return {*}
 * @Date: 2022-03-05 13:16:57
 */
Picker.prototype._adjustTenYear = function (button, type) {
    let $button = $(button),
        $container = $button.closest(this.CONTAINER),
        $body = $container.find(this.BODY),
        startYear = $button.siblings('.year').attr('data-value');

    if (type === 'prev') {
        startYear = parseInt(startYear) - 10;
    } else if (type === 'next') {
        startYear = parseInt(startYear) + 10;
    }
    let inputValue = $button.closest(this.CONTAINER).find(this.INPUT).val();

    $body.find(this.BODY_YEAR).remove();
    $body.append(this._bodyYearHtml({ inputValue, year: startYear }));
};

/**
 * @description: 生成 月份 html
 * @param {*} inputValue    输入框 月份
 * @param {*} year          年份
 * @param {*} month         月份
 * @param {*} isHidden      是否隐藏
 * @return {*}
 * @Date: 2022-03-05 19:48:39
 */
Picker.prototype._bodyMonthHtml = function ({ inputValue, year, month }, isHidden) {
    const MONTHLIST = ['一月', '二月', '三月', '四月', '五月', '六月', '七月', '八月', '九月', '十月', '十一月', '十二月'];
    let htmlArr = [];

    let { year: nowYear, month: nowMonth } = _nowDatetime();

    year = parseInt(year) || nowYear;
    month = parseInt(month) || nowMonth;

    for (let i = 0; i < 12; i++) {
        let classArr = ['available'];
        year === nowYear && i === nowMonth - 1 && classArr.push('today');
        `${year}-${i + 1 < 10 ? '0' + (i + 1) : i + 1}` === inputValue && classArr.push('current');

        htmlArr.push(`<td class="${classArr.join(' ')}" data-value="${year}-${i + 1 < 10 ? '0' + (i + 1) : i + 1}"><span class="cell">${MONTHLIST[i]}</span></td>`);
    }

    // foxui-picker-header html
    let headerHtml = this._headerHtml({ year }, 'month');

    // foxui-picker-content hmtl
    let contentHtml = this._contentHtml({
        htmlArr,
        num: 4,
        type: 'month',
        isHidden: false,
    });

    return `<div class="foxui-picker-body__month" style="${!isHidden ? '' : 'display: none'}">${headerHtml + contentHtml}</div>`;
};

Picker.prototype._bindAdjustYear = function () {
    let that = this;
    $(document).on('click', this.PREV_YEAR_BTN_YEAR, function () {
        that._adjustYearForMonth(this, 'prev');
    });

    $(document).on('click', this.NEXT_YEAR_BTN_YEAR, function () {
        that._adjustYearForMonth(this, 'next');
    });
};

/**
 * @description: 前/后一年 (foxui-picker-body__month)
 * @param {*} button     点击按钮
 * @param {*} type       类型：next, prev
 * @return {*}
 * @Date: 2022-03-05 20:56:04
 */
Picker.prototype._adjustYearForMonth = function (button, type) {
    let $button = $(button),
        $container = $button.closest(this.CONTAINER),
        $body = $container.find(this.BODY),
        year = $button.siblings('.year').attr('data-value');

    if (type === 'prev') {
        year = parseInt(year) - 1;
    } else if (type === 'next') {
        year = parseInt(year) + 1;
    }
    let inputValue = $button.closest(this.CONTAINER).find(this.INPUT).val();

    $body.find(this.BODY_MONTH).remove();
    $body.append(this._bodyMonthHtml({ inputValue, year }));
};

/**
 * @description: 生成 日期 html
 * @param {*} inputValue     输入框 月份
 * @param {*} year           年份
 * @param {*} month          月份
 * @param {*} date           日期
 * @param {*} isHidden       是否隐藏
 * @return {*}
 * @Date: 2022-03-05 22:59:50
 */
Picker.prototype._bodyDateHtml = function ({ inputValue, year, month }, isHidden) {
    let { year: nowYear, month: nowMonth, date: today } = _nowDatetime();

    year = parseInt(year) || nowYear;
    month = parseInt(month) || nowMonth;

    let setDate = new Date();
    // 设置年份
    setDate.setFullYear(year);
    // 设置月份，因为系统的月份都是比真实的小1
    setDate.setMonth(month - 1);
    // 设置成当前月第一天
    setDate.setDate(1);
    //得到本月第一天是星期几
    let week = setDate.getDay();
    //设置成正确的真实月份
    setDate.setMonth(month);
    //计算得到当前月最后一天的日期格式
    let lastDate = new Date(setDate.getTime() - 1000 * 60 * 60 * 24);
    //获取本月最后一天是几号
    let lastDay = lastDate.getDate();
    //利用得到的当前月总天数来循环出当前月日历
    let htmlArr = [];
    // 第一行补全上个月的天数
    for (let i = 0; i < week; i++) {
        htmlArr.push('<td class="prev-month"><div><span></span></div></td>');
    }

    // 当前月的天数
    for (let i = 1; i <= lastDay; i++) {
        let classArr = ['available'];

        // 判断是不是今天
        if (parseInt(year) === nowYear && parseInt(month) === nowMonth && i === today) {
            classArr.push('today');
        }
        // 判断是不是输入框时期
        if (`${year}-${month < 10 ? '0' + month : month}-${i < 10 ? '0' + i : i}` === inputValue) {
            classArr.push('current');
        }

        htmlArr.push(`<td data-value="${year}-${month < 10 ? '0' + month : month}-${i < 10 ? '0' + i : i}" class="${classArr.join(' ')}"><div><span>${i < 10 ? '0' + i : i}</span></div></td>`);
    }

    // 生成html，每7天一组
    let tbodyInnerHtml = '';
    for (var i = 0, len = htmlArr.length; i < len; i += 7) {
        tbodyInnerHtml += `<tr>${htmlArr.slice(i, i + 7).join('')}</tr>`;
    }
    let theadInnerHtml = ['<tr>', '<th>日</th>', '<th>一</th>', '<th>二</th>', '<th>三</th>', '<th>四</th>', '<th>五</th>', '<th>六</th>', '</tr>'].join('');

    // foxui-picker-header html
    let headerHtml = this._headerHtml({ year, month }, 'date');

    // foxui-picker-content hmtl
    let contentHtml = [
        '<div class="foxui-picker-content">',
        `<table cellspacing="0" cellpadding="0" class="foxui-date-table" style="${!isHidden ? '' : 'display: none'}">`,
        '<thead>',
        `${theadInnerHtml}`,
        '</thead>',
        '<tbody>',
        `${tbodyInnerHtml}`,
        '</tbody>',
        '</table>',
        '</div>',
    ].join('');

    return `<div class="foxui-picker-body__date" style="${!isHidden ? '' : 'display: none'}">${headerHtml + contentHtml}</div>`;
};

/**
 * @description: 绑定日期面板 上一年/下一年/上一个月/下一个月
 * @param {*}
 * @return {*}
 * @Date: 2022-03-06 01:41:21
 */
Picker.prototype._bindAdjustDate = function () {
    let that = this;
    $(document).on('click', this.PREV_YEAR_BTN_DATE, function () {
        that._adjustDate(this, 'prevYear');
    });

    $(document).on('click', this.NEXT_YEAR_BTN_DATE, function () {
        that._adjustDate(this, 'nextYear');
    });

    $(document).on('click', this.PREV_DATE_BTN, function () {
        that._adjustDate(this, 'prevMonth');
    });

    $(document).on('click', this.NEXT_DATE_BTN, function () {
        that._adjustDate(this, 'nextMonth');
    });
};

/**
 * @description: 日期面板 调整：上一年/下一年/上一个月/下一个月
 * @param {*} button    按钮
 * @param {*} type      类型：prevYear、nextYear、prevMonth、nextMonth
 * @return {*}
 * @Date: 2022-03-06 01:41:55
 */
Picker.prototype._adjustDate = function (button, type) {
    let $button = $(button),
        $body = $button.closest(this.CONTAINER).find(this.BODY),
        year = $button.siblings('.year').attr('data-value'),
        month = $button.siblings('.month').attr('data-value'),
        inputValue = $button.closest(this.CONTAINER).find(this.INPUT).val();

    switch (type) {
        case 'prevYear':
            year--;
            break;
        case 'nextYear':
            year++;
            break;
        case 'prevMonth':
            if (month > 1) {
                month--;
            } else {
                month = 12;
                year--;
            }
            break;
        case 'nextMonth':
            if (month < 12) {
                month++;
            } else {
                month = 1;
                year++;
            }
            break;
        default:
            false;
    }

    $body.find(this.BODY_DATE).remove();
    $body.append(this._bodyDateHtml({ inputValue, year, month }));
};

/**
 * @description: 日期输入框填入值
 * @param {*}
 * @return {*}
 * @Date: 2022-03-05 18:15:41
 */
Picker.prototype._bindFillInput = function () {
    let that = this;
    $(document).on('click', this.FILL_INPUT_HANDLE, function () {
        let $this = $(this);
        let $container = $this.closest(that.CONTAINER);
        let value = $this.attr('data-value');
        $container.find(that.INPUT).val(value);
        // CLEAR_HANDLE 些时 就是 foxui-picker-handle
        $container.find(that.CLEAR_HANDLE).removeClass('is-active');
        $container.find(that.MENU).slideUp('fast');
    });
};

/**
 * @description: 跳转至 年份 面板
 * @param {*}
 * @return {*}
 * @Date: 2022-03-05 21:41:26
 */
Picker.prototype._bindJumpYear = function () {
    let that = this;
    $(document).on('click', this.JUMP_YEAR_HANDLE, function () {
        let $this = $(this),
            $container = $this.closest(that.CONTAINER),
            $body = $container.find(that.BODY);

        let year = $this.attr('data-value'),
            inputValue = $container.find(that.INPUT).val();

        $body.find(that.BODY_YEAR).remove();
        $body.find(that.BODY_MONTH).css('display', 'none');
        $body.find(that.BODY_DATE).css('display', 'none');
        $body.append(that._bodyYearHtml({ inputValue, year }));
    });
};

/**
 * @description: 跳转至 月份 面板
 * @param {*}
 * @return {*}
 * @Date: 2022-03-05 22:46:32
 */
Picker.prototype._bindJumpMonth = function () {
    let that = this;
    $(document).on('click', this.JUMP_MONTH_HANDLE, function () {
        let $this = $(this),
            $container = $this.closest(that.CONTAINER),
            $body = $container.find(that.BODY);

        let year = $this.attr('data-value'),
            month = '',
            inputValue = $container.find(that.INPUT).val();

        // 如果点击的是日期面板月份，纠正 year、month、inputValue
        if ($this.is('.month')) {
            year = $this.siblings('.year').attr('data-value');
            month = $this.attr('data-value');

            let arr = [];
            arr = inputValue.split('-');
            arr.pop();
            inputValue = arr.join('-');
        }

        $body.find(that.BODY_MONTH).remove();
        $body.find(that.BODY_YEAR).css('display', 'none');
        $body.find(that.BODY_DATE).css('display', 'none');
        $body.append(that._bodyMonthHtml({ inputValue, year, month }));
    });
};

Picker.prototype._bindJumpDate = function () {
    let that = this;
    $(document).on('click', this.JUMP_DATE_HANDLE, function () {
        let $this = $(this),
            $container = $this.closest(that.CONTAINER),
            $body = $container.find(that.BODY);

        let yearMonthArr = $this.attr('data-value').split('-'),
            inputValue = $container.find(that.INPUT).val();

        $body.find(that.BODY_DATE).remove();
        $body.find(that.BODY_YEAR).css('display', 'none');
        $body.find(that.BODY_MONTH).css('display', 'none');
        $body.append(that._bodyDateHtml({ inputValue, year: yearMonthArr[0], month: yearMonthArr[1] }));
    });
};

let picker = new Picker();

export { Picker, picker };
